package com.agilestudio.ifinance.web.account;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

import com.agilestudio.ifinance.entity.IdEntity;
import com.agilestudio.ifinance.entity.account.Menu;
import com.agilestudio.ifinance.entity.account.Role;
import com.agilestudio.ifinance.entity.account.User;
import com.agilestudio.ifinance.web.AbstractController;
import com.agilestudio.modules.orm.Page;
import com.agilestudio.modules.orm.PropertyFilter;

@Controller
@RequestMapping(value = "role")
public class RoleController extends AbstractController {

	@RequestMapping(value = "list", method = RequestMethod.GET)
	public String list(Map<String, Object> map) {
		log.info("RequestMethod.GET role list...");
		initMenus(map);
		return "role/list";
	}

	@RequestMapping(value = "add", method = RequestMethod.GET)
	public ModelAndView add(Map<String, Object> map) {
		log.info("RequestMethod.GET role add...");
		initMenus(map);
		ModelAndView mav = new ModelAndView("role/add");
		StringBuffer sb = setupTree(null);
		mav.addObject("mytree", sb.toString());
		return mav;
	}

	@RequestMapping(value = "/edit/{id}", method = RequestMethod.GET)
	public ModelAndView edit(Map<String, Object> map, @PathVariable String id) {
		log.info("RequestMethod.GET role edit..." + id);
		initMenus(map);
		ModelAndView mav = new ModelAndView("role/edit");
		Role role = accountService.getRole(Long.valueOf(id));
		mav.addObject("role", role);
		StringBuffer sb = setupTree(role.getMenus());
		log.info("mytree = " + sb.toString());
		mav.addObject("mytree", sb.toString());
		return mav;
	}

	public StringBuffer setupTree(List<Menu> ownedMenus) {
		List<Menu> menus = accountService.getOrganizedMenus();
		StringBuffer sb = new StringBuffer();
		setupTree(menus, sb, ownedMenus);
		return sb;
	}

	private void setupTree(List<Menu> menus, StringBuffer sb,
			List<Menu> ownedMenus) {
		sb.append("<ul>");
		for (Menu menu : menus) {
			sb.append("<li class='"
					+ (menu.isLeaf() ? (in(menu, ownedMenus) ? "jstree-leaf jstree-checked"
							: "jstree-leaf")
							: "jstree-closed") + "' rel='"
					+ (menu.isLeaf() ? "file" : "folder") + "' id='"
					+ menu.getId() + "'><a>" + menu.getName() + "</a>");
			setupTree(menu.getMenus(), sb, ownedMenus);
		}
		sb.append("</ul>");
	}

	private boolean in(final IdEntity e,
			final List<? extends IdEntity> ownedMenus) {
		if (ownedMenus == null || ownedMenus.size() == 0)
			return false;
		for (IdEntity e2 : ownedMenus) {
			if (e2.getId() == e.getId())
				return true;
		}
		return false;
	}

	public List<Menu> getOrganizedMenus() {
		List<Menu> menus = accountService.getMenus();
		List<Menu> organizedMenus = new ArrayList<Menu>();
		for (Iterator<Menu> iterator = menus.iterator(); iterator.hasNext();) {
			Menu menu = (Menu) iterator.next();
			if (menu.getCode().endsWith("000000")) {
				List<Menu> children = new ArrayList<Menu>();
				menu.setMenus(children);
				for (Iterator<Menu> iterator2 = menus.iterator(); iterator2
						.hasNext();) {
					Menu menu2 = (Menu) iterator2.next();
					if (!menu2.getCode().equals(menu.getCode())
							&& menu2.getCode().startsWith(
									menu.getCode().substring(0, 2))) {
						children.add(menu2);
					}
				}
				organizedMenus.add(menu);
			}
		}
		return organizedMenus;
	}

	// @RequestMapping(value = "list", method = RequestMethod.POST)
	// public @ResponseBody
	// Map<String, Object> list(WebRequest wr, FlexiGrid<Role> flexiGrid) {
	// for (Map.Entry<String, String[]> s : wr.getParameterMap().entrySet()) {
	// log.info("list 0000------" + s.getKey() + ":" + s.getValue()[0]);
	// }
	// Page<Role> page = flexiGrid;
	// log.info("list ######## = " + flexiGrid);
	// List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
	// if (flexiGrid != null && flexiGrid.getAddparams() != null) {
	// for (int i = 0; i < flexiGrid.getAddparams().size(); i++) {
	// log.info("list 22222----------"
	// + flexiGrid.getAddparams().get(i).toString());
	// filters.add(new PropertyFilter("LIKE", "S", flexiGrid
	// .getAddparams().get(i).getName(), flexiGrid
	// .getAddparams().get(i).getValue().toString()));
	// }
	// }
	// page = accountService.searchRole(flexiGrid, filters);
	// List<Role> roles = flexiGrid.getRows();
	// List<Map<String, ? extends Object>> rows = new ArrayList<Map<String, ?
	// extends Object>>();
	// for (Role role : roles) {
	// Map<String, Object> node = new HashMap<String, Object>();
	// List<String> metadata = new ArrayList<String>();
	// node.put("id", role.getId());
	// metadata.add(role.getId().toString());
	// metadata.add(role.getCode());
	// metadata.add(role.getName());
	// metadata.add(role.getDesc());
	// node.put("cell", metadata);
	// rows.add(node);
	// }
	// Map<String, Object> map = new HashMap<String, Object>();
	// map.put("page", page.getPage());
	// map.put("rows", rows);
	// map.put("total", page.getTotal());
	// return map;
	// }

	@RequestMapping(value = "list", method = RequestMethod.POST)
	public String list(Map<String, Object> map, WebRequest wr, Page<Role> page) {
		for (Map.Entry<String, String[]> s : wr.getParameterMap().entrySet()) {
			log.info("list 0000------" + s.getKey() + ":"
					+ ToStringBuilder.reflectionToString(s.getValue()) + ":"
					+ s.getValue().length);
		}
		log.info("list ######## = " + page);
		initMenus(map);
		List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
		page = accountService.searchRole(page, filters);
		map.put("page", page);
		return "role/list";
	}

	@RequestMapping(value = "save", method = RequestMethod.POST)
	public ModelAndView save(Map<String, Object> map, @Valid Role role,
			BindingResult result) {
		initMenus(map);
		log.info("save = " + role.toString());
		for (FieldError fe : result.getFieldErrors()) {
			log.info("save error FieldError= " + fe.getField() + ";"
					+ fe.getCode() + ";" + fe.getDefaultMessage());
		}
		ModelAndView mav = new ModelAndView("role/edit");
		if (result.hasErrors()) {
			if (role.getId() == null) {
				mav.setViewName("role/add");
				mav.addObject("role", role);
				mav.addObject("mytree", setupTree(role.getMenus()).toString());
			} else {
				Role o = accountService.getRole(role.getId());
				mav.addObject("role", o);
				mav.addObject("mytree", setupTree(o.getMenus()).toString());
			}
			return mav;
		} else {
			if (role.getId() == null) {
				role.getMenus().clear();
				for (Long id : role.getMenuIds()) {
					if (id != null) {
						role.getMenus().add(accountService.getMenu(id));
					}
				}
				accountService.saveRole(role);
				mav.addObject("role", role);
				mav.addObject("mytree", setupTree(role.getMenus()).toString());
			} else {
				Role o = accountService.getRole(role.getId());
				o.setCode(role.getCode());
				o.setName(role.getName());
				o.setDesc(role.getDesc());
				o.getMenus().clear();
				for (Long id : role.getMenuIds()) {
					if (id != null) {
						o.getMenus().add(accountService.getMenu(id));
					}
				}
				accountService.saveRole(o);
				mav.addObject("role", o);
				mav.addObject("mytree", setupTree(o.getMenus()).toString());
			}
			return mav;
		}
	}

	@RequestMapping(value = "delete", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, String> delete(@RequestParam("id") Long id) {
		log.info("delete1 = " + id);
		accountService.deleteRole(id);
		Map<String, String> map = new HashMap<String, String>();
		map.put("info", "success");
		return map;
	}

	@RequestMapping(value = "loadRoleMenu", method = RequestMethod.POST)
	public @ResponseBody
	Map<String, Object> loadRoleMenu(@RequestParam("sortname") String sortname,
			@RequestParam("sortorder") String sortorder) {
		log.info("loadRoleMenus..." + "sortname=" + sortname + ";sortorder="
				+ sortorder);
		List<Map<String, ? extends Object>> rows = new ArrayList<Map<String, ? extends Object>>();
		List<PropertyFilter> filters = new ArrayList<PropertyFilter>();
		List<Menu> menus = accountService.searchMenu(filters);
		for (Menu menu : menus) {
			Map<String, Object> node = new HashMap<String, Object>();
			List<String> metadata = new ArrayList<String>();
			node.put("id", menu.getId());
			metadata.add(menu.getId().toString());
			metadata.add(menu.getCode());
			metadata.add(menu.getName());
			metadata.add(menu.getUrl());
			metadata.add(String.valueOf(menu.isLeaf()));
			node.put("cell", metadata);
			rows.add(node);
		}
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("rows", rows);
		map.put("total", menus.size());
		return map;
	}
}
